package com.example.config.mybatis;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

/**
* @Author: jintao123
 * @Date: 2017/5/4 11:24
* @Desc: 数据源配置
*/
@Configuration
@EnableTransactionManagement
public class MyBatisConfiguration {
    @Autowired
    private Environment env;

    private String driveClassName;
    private String url;
    private String userName;
    private String password;
    private String xmlLocation;
    private String typeAliasesPackage;
    // ///////////////////druid参数///////////////////////////////////////////////////
    private String filters;
    private String maxActive;
    private String initialSize;
    private String maxWait;
    private String minIdle;
    private String timeBetweenEvictionRunsMillis;
    private String minEvictableIdleTimeMillis;
    private String validationQuery;
    private String testWhileIdle;
    private String testOnBorrow;
    private String testOnReturn;
    private String poolPreparedStatements;
    private String maxOpenPreparedStatements;

    // ////////////////////////////////////////////////////////////////////////

    @Bean(name="druidDataSource")
    public DataSource druidDataSource() {
        init();
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(password);
        druidDataSource.setDriverClassName(StringUtils
                .isNotBlank(driveClassName) ? driveClassName
                : "com.mysql.jdbc.Driver");
        druidDataSource
                .setMaxActive(StringUtils.isNotBlank(maxActive) ? Integer
                        .parseInt(maxActive) : 10);
        druidDataSource
                .setInitialSize(StringUtils.isNotBlank(initialSize) ? Integer
                        .parseInt(initialSize) : 1);
        druidDataSource.setMaxWait(StringUtils.isNotBlank(maxWait) ? Integer
                .parseInt(maxWait) : 60000);
        druidDataSource.setMinIdle(StringUtils.isNotBlank(minIdle) ? Integer
                .parseInt(minIdle) : 3);
        druidDataSource.setTimeBetweenEvictionRunsMillis(StringUtils
                .isNotBlank(timeBetweenEvictionRunsMillis) ? Integer
                .parseInt(timeBetweenEvictionRunsMillis) : 60000);
        druidDataSource.setMinEvictableIdleTimeMillis(StringUtils
                .isNotBlank(minEvictableIdleTimeMillis) ? Integer
                .parseInt(minEvictableIdleTimeMillis) : 300000);
        druidDataSource.setValidationQuery(StringUtils
                .isNotBlank(validationQuery) ? validationQuery : "select 'x'");
        druidDataSource
                .setTestWhileIdle(StringUtils.isNotBlank(testWhileIdle) ? Boolean
                        .parseBoolean(testWhileIdle) : true);
        druidDataSource
                .setTestOnBorrow(StringUtils.isNotBlank(testOnBorrow) ? Boolean
                        .parseBoolean(testOnBorrow) : false);
        druidDataSource
                .setTestOnReturn(StringUtils.isNotBlank(testOnReturn) ? Boolean
                        .parseBoolean(testOnReturn) : false);
        druidDataSource.setPoolPreparedStatements(StringUtils
                .isNotBlank(poolPreparedStatements) ? Boolean
                .parseBoolean(poolPreparedStatements) : true);
        druidDataSource.setMaxOpenPreparedStatements(StringUtils
                .isNotBlank(maxOpenPreparedStatements) ? Integer
                .parseInt(maxOpenPreparedStatements) : 20);

        try {
            druidDataSource
                    .setFilters(StringUtils.isNotBlank(filters) ? filters
                            : "stat, wall");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return druidDataSource;
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("druidDataSource")DataSource dataSource) {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        if (StringUtils.isNotBlank(typeAliasesPackage)) {
            bean.setTypeAliasesPackage(typeAliasesPackage);
        }
        // 分页插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);
        // 添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            bean.setMapperLocations(resolver.getResources(xmlLocation));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean(name="sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(
            @Qualifier("sqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    public void init() {
        this.url = env.getProperty("spring.datasource.url");
        this.userName = env.getProperty("spring.datasource.username");
        this.password = env.getProperty("spring.datasource.password");
        this.driveClassName = env
                .getProperty("spring.datasource.driver-class-name");
        this.filters = env.getProperty("spring.datasource.filters");
        this.maxActive = env.getProperty("spring.datasource.maxActive");
        this.initialSize = env.getProperty("spring.datasource.initialSize");
        this.maxWait = env.getProperty("spring.datasource.maxWait");
        this.minIdle = env.getProperty("spring.datasource.minIdle");
        this.timeBetweenEvictionRunsMillis = env
                .getProperty("spring.datasource.timeBetweenEvictionRunsMillis");
        this.minEvictableIdleTimeMillis = env
                .getProperty("spring.datasource.minEvictableIdleTimeMillis");
        this.validationQuery = env
                .getProperty("spring.datasource.validationQuery");
        this.testWhileIdle = env.getProperty("spring.datasource.testWhileIdle");
        this.testOnBorrow = env.getProperty("spring.datasource.testOnBorrow");
        this.testOnReturn = env.getProperty("spring.datasource.testOnReturn");
        this.poolPreparedStatements = env
                .getProperty("spring.datasource.poolPreparedStatements");
        this.maxOpenPreparedStatements = env
                .getProperty("spring.datasource.maxOpenPreparedStatements");
        this.typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
        this.xmlLocation = env.getProperty("mybatis.xmlLocation");
    }

    @Bean(name="transactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("druidDataSource")DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

